package com.ruoyi.ldzlsc.service.Impl;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Date;
import java.util.stream.Collectors;
import java.math.BigDecimal;
import lombok.extern.slf4j.Slf4j;

import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.api.BasicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.ldzlsc.mapper.ScProductionOrderMapper;
import com.ruoyi.ldzlsc.mapper.ScProductionOrderDetailMapper;
import com.ruoyi.ldzlsc.domain.ScProductionOrder;
import com.ruoyi.ldzlsc.domain.ScProductionOrderDetail;
import com.ruoyi.ldzlsc.domain.vo.ScProductionPlanVo;
import com.ruoyi.ldzlsc.service.ScProductionOrderService;
import com.ruoyi.ldzlsc.service.IScProductionPlanService;
import com.ruoyi.ldzlsc.service.ScProductInventoryService;

/**
 * 生产订单Service业务层处理
 * 
 * @author ldzl
 * @date 2023-09-15
 */
@Slf4j
@Service
public class ScProductionOrderServiceImpl implements ScProductionOrderService
{
    @Autowired
    private ScProductionOrderMapper scProductionOrderMapper;

    @Autowired
    private ScProductionOrderDetailMapper scProductionOrderDetailMapper;

    @Autowired
    private IScProductionPlanService scProductionPlanService;


    @Autowired
    private BasicService basicService;

    @Autowired
    private ScProductInventoryService scProductInventoryService;

    /**
     * 查询生产订单列表
     * 
     * @param scProductionOrder 生产订单
     * @return 生产订单集合
     */
    @Override
    public List<ScProductionOrder> selectScProductionOrderList(ScProductionOrder scProductionOrder)
    {
        return scProductionOrderMapper.selectScProductionOrderList(scProductionOrder);
    }

    /**
     * 查询生产订单详情，包括产品明细、生产计划、工单
     *
     * @param id 生产订单主键
     * @return 包含完整信息的生产订单
     */
    @Override
    public ScProductionOrder selectScProductionOrderWithAllDetails(Long id)
    {
        // 查询订单基本信息
        ScProductionOrder order = scProductionOrderMapper.selectScProductionOrderById(id);
        if (order == null) {
            return null;
        }
        
        // 查询订单明细
        List<ScProductionOrderDetail> details = scProductionOrderDetailMapper.selectScProductionOrderDetailByOrderId(id);
        order.setProducts(details);
        
        // 查询生产计划
        List<Map<String, Object>> plans = scProductionOrderDetailMapper.selectProductionPlanByOrderId(id);
        log.info("查询生产订单[{}]的生产计划，找到{}条记录", id, plans != null ? plans.size() : 0);
        if (plans != null && !plans.isEmpty()) {
            for (Map<String, Object> plan : plans) {
                log.info("生产计划详情：{}", plan);
            }
        }
        order.setPlans(plans);
        
        // 查询工单
        List<Map<String, Object>> workOrders = scProductionOrderDetailMapper.selectWorkOrderByOrderId(id);
        order.setWorkOrders(workOrders);
        
        return order;
    }
    
    /**
     * 新增生产订单
     *
     * @param scProductionOrder 生产订单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertScProductionOrder(ScProductionOrder scProductionOrder)
    {
        // 添加调试日志
        log.info("=== Service层生产订单新增调试信息 ===");
        log.info("订单编号: {}", scProductionOrder.getProdOrderCode());
        log.info("自动生成计划标记: {}", scProductionOrder.getAutoGeneratePlan());
        log.info("原始状态: {}", scProductionOrder.getStatus());

        // 设置创建时间、创建人等信息
        scProductionOrder.setCreateTime(DateUtils.getNowDate());
        scProductionOrder.setCreateBy(SecurityUtils.getUsername());

        // 设置状态：如果选择自动生成计划则为"生产中"，否则为"待计划"
        if (scProductionOrder.getStatus() == null) {
            if (scProductionOrder.getAutoGeneratePlan() != null && scProductionOrder.getAutoGeneratePlan()) {
                scProductionOrder.setStatus("2"); // 生产中
                log.info("设置状态为生产中(2)，因为autoGeneratePlan=true");
            } else {
                scProductionOrder.setStatus("1"); // 待计划
                log.info("设置状态为待计划(1)，因为autoGeneratePlan=false或null");
            }
        }

        log.info("最终状态: {}", scProductionOrder.getStatus());

        // 设置库存检查标记默认值：0=未检查
        if (scProductionOrder.getStockCheck() == null) {
            scProductionOrder.setStockCheck("0");
        }

        // 设置库存充足标记默认值：1=库存充足（默认假设）
        if (scProductionOrder.getStockEnough() == null) {
            scProductionOrder.setStockEnough("1");
        }

        if (scProductionOrder.getSalesOrderId() == null) {
            scProductionOrder.setSalesOrderId(null);
        }

        // 插入订单主表
        int rows = scProductionOrderMapper.insertScProductionOrder(scProductionOrder);

        // 插入订单明细
        insertScProductionOrderDetail(scProductionOrder);

        // 如果选择自动生成生产计划，则创建对应的生产计划
        if (scProductionOrder.getAutoGeneratePlan() != null && scProductionOrder.getAutoGeneratePlan()) {
            log.info("开始自动生成生产计划...");
            autoGenerateProductionPlans(scProductionOrder);
            log.info("自动生成生产计划完成");
        } else {
            log.info("未选择自动生成计划，跳过生产计划创建");
        }

        return rows;
    }
    
    /**
     * 修改生产订单
     * 
     * @param scProductionOrder 生产订单
     * @return 结果
     */
    @Override
    @Transactional
    public int updateScProductionOrder(ScProductionOrder scProductionOrder)
    {
        // 设置更新时间、更新人等信息
        scProductionOrder.setUpdateTime(DateUtils.getNowDate());
        scProductionOrder.setUpdateBy(SecurityUtils.getUsername());
        
        // 删除原有明细
        scProductionOrderDetailMapper.deleteScProductionOrderDetailByOrderId(scProductionOrder.getProductionOrderId());
        
        // 插入新明细
        insertScProductionOrderDetail(scProductionOrder);
        
        // 更新订单主表
        return scProductionOrderMapper.updateScProductionOrder(scProductionOrder);
    }
    
    /**
     * 批量删除生产订单
     * 
     * @param ids 需要删除的生产订单主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteScProductionOrderByIds(Long[] ids)
    {
        // 删除关联的明细数据
        for (Long id : ids) {
            scProductionOrderDetailMapper.deleteScProductionOrderDetailByOrderId(id);
        }
        
        // 删除订单主表数据
        return scProductionOrderMapper.deleteScProductionOrderByIds(ids);
    }
    

    
    /**
     * 新增生产订单明细信息
     * 
     * @param scProductionOrder 生产订单对象
     */
    private void insertScProductionOrderDetail(ScProductionOrder scProductionOrder)
    {
        List<ScProductionOrderDetail> products = scProductionOrder.getProducts();
        
        if (products != null && !products.isEmpty()) {
            List<ScProductionOrderDetail> list = new ArrayList<>();
            
            for (ScProductionOrderDetail detail : products) {
                detail.setProductionOrderId(scProductionOrder.getProductionOrderId());
                detail.setProdOrderCode(scProductionOrder.getProdOrderCode());
                detail.setCreateTime(DateUtils.getNowDate());
                detail.setCreateBy(SecurityUtils.getUsername());
                
                // 设置交付日期，如果明细没有设置则使用订单的交付日期
                if (detail.getDeliveryDate() == null) {
                    detail.setDeliveryDate(scProductionOrder.getDeliveryDate());
                }
                
                list.add(detail);
            }
            
            if (list.size() > 0) {
                scProductionOrderDetailMapper.batchInsertScProductionOrderDetail(list);
            }
        }
    }

    /**
     * 根据生产订单自动生成生产计划
     *
     * @param scProductionOrder 生产订单
     */
    private void autoGenerateProductionPlans(ScProductionOrder scProductionOrder) {
        List<ScProductionOrderDetail> products = scProductionOrder.getProducts();
        if (products == null || products.isEmpty()) {
            return;
        }

        String username = SecurityUtils.getUsername();
        Date currentTime = DateUtils.getNowDate();

        // 收集所有产品ID用于批量查询库存
        List<Long> productIds = products.stream()
                .map(ScProductionOrderDetail::getProductId)
                .collect(Collectors.toList());

        log.info("准备查询库存，产品ID列表：{}", productIds);

        // 批量查询库存数量
        Map<Long, Integer> stockQuantities = null;
        try {
            stockQuantities = scProductInventoryService.getProductStockQuantities(productIds);
            log.info("库存查询结果：{}", stockQuantities);
        } catch (Exception e) {
            log.error("查询库存失败，将使用默认值0", e);
            stockQuantities = new HashMap<>();
            for (Long productId : productIds) {
                stockQuantities.put(productId, 0);
            }
        }

        // 统计需要生产的产品数量，用于更新库存充足标记
        int totalProducts = products.size();
        int productsNeedProduction = 0;

        log.info("=== 开始处理生产订单产品明细，总数量：{} ===", totalProducts);

        // 为每个产品明细创建对应的生产计划
        for (ScProductionOrderDetail product : products) {
            log.info("=== 处理产品明细 ===");
            log.info("产品ID：{}，产品名称：{}，需求数量：{}",
                product.getProductId(), product.getProductName(), product.getQtyNum());

            // 获取当前库存数量
            int currentStock = stockQuantities.getOrDefault(product.getProductId(), 0);
            log.info("当前库存数量：{}", currentStock);

            // 计算实际需要生产的数量 = 需求数量 - 库存数量
            BigDecimal demandQty = product.getQtyNum();
            BigDecimal actualProductionQty = demandQty.subtract(new BigDecimal(currentStock));
            log.info("计算结果：需求数量({}) - 库存数量({}) = 实际生产数量({})",
                demandQty, currentStock, actualProductionQty);

            // 如果实际生产数量 <= 0，则不需要生产，跳过
            if (actualProductionQty.compareTo(BigDecimal.ZERO) <= 0) {
                log.info("产品[{}]库存充足，无需生产。需求数量：{}，库存数量：{}",
                    product.getProductName(), demandQty, currentStock);
                continue;
            }

            // 统计需要生产的产品数量
            productsNeedProduction++;
            log.info("产品[{}]需要生产，实际生产数量：{}", product.getProductName(), actualProductionQty);

            ScProductionPlanVo planVo = new ScProductionPlanVo();

            // 生成计划编号
            String planCode = generateCode(6L);
            planVo.setPlanCode(planCode);

            String orderShort = scProductionOrder.getProdOrderCode().substring(scProductionOrder.getProdOrderCode().length() - 4);
            planVo.setPlanName(product.getProductName() + "计划(" + orderShort + ")");

            // 关联生产订单
            planVo.setProductionOrderId(scProductionOrder.getProductionOrderId());

            // 设置产品信息
            planVo.setProductId(product.getProductId());
            planVo.setPlannedQty(actualProductionQty); // 使用计算后的实际生产数量

            // 设置来源类型为生产订单
            planVo.setSourceType("生产订单");

            // 设置时间信息（可以根据交付日期计算）
            if (product.getDeliveryDate() != null) {
                planVo.setRequiredDate(product.getDeliveryDate());
                // 可以根据生产周期计算计划开始和结束时间
                planVo.setPlanStartTime(currentTime);
                planVo.setPlanEndTime(product.getDeliveryDate());
            }

            // 设置创建信息
            planVo.setCreateBy(username);
            planVo.setCreateTime(currentTime);
            planVo.setRemark("由生产订单[" + scProductionOrder.getProdOrderCode() + "]自动生成，需求数量："
                + demandQty + "，库存数量：" + currentStock + "，实际生产数量：" + actualProductionQty);

            log.info("=== 准备创建生产计划 ===");
            log.info("计划编号：{}", planVo.getPlanCode());
            log.info("计划名称：{}", planVo.getPlanName());
            log.info("关联生产订单ID：{}", planVo.getProductionOrderId());
            log.info("产品ID：{}", planVo.getProductId());
            log.info("计划数量：{}", planVo.getPlannedQty());
            log.info("来源类型：{}", planVo.getSourceType());

            // 调用生产计划服务创建计划
            int planResult = scProductionPlanService.insertProductionPlan(planVo);

            if (planResult > 0) {
                log.info("已成功创建生产计划[{}]，产品：{}，实际生产数量：{}，生产计划ID：{}",
                    planCode, product.getProductName(), actualProductionQty, planVo.getProductionPlanId());
            } else {
                log.error("创建生产计划失败[{}]，产品：{}，实际生产数量：{}",
                    planCode, product.getProductName(), actualProductionQty);
            }
        }

        log.info("=== 生产计划创建完成，总产品数：{}，需要生产数：{}，库存充足数：{} ===",
            totalProducts, productsNeedProduction, totalProducts - productsNeedProduction);

        // 更新生产订单的库存充足标记
        updateStockEnoughFlag(scProductionOrder, totalProducts, productsNeedProduction);
    }

    /**
     * 更新生产订单的库存充足标记
     * @param scProductionOrder 生产订单对象
     * @param totalProducts 总产品数量
     * @param productsNeedProduction 需要生产的产品数量
     */
    private void updateStockEnoughFlag(ScProductionOrder scProductionOrder, int totalProducts, int productsNeedProduction) {
        // 如果没有产品需要生产，说明库存充足
        String stockEnoughFlag = (productsNeedProduction == 0) ? "1" : "0";

        log.info("库存充足标记更新：总产品数量={}，需要生产数量={}，库存充足标记={}",
            totalProducts, productsNeedProduction, stockEnoughFlag);

        // 更新生产订单的库存充足标记
        ScProductionOrder updateOrder = new ScProductionOrder();
        updateOrder.setProductionOrderId(scProductionOrder.getProductionOrderId());
        updateOrder.setStockEnough(stockEnoughFlag);
        updateOrder.setStockCheck("1"); // 标记为已检查

        try {
            int result = scProductionOrderMapper.updateScProductionOrder(updateOrder);
            if (result > 0) {
                log.info("生产订单[{}]库存充足标记更新成功：{}",
                    scProductionOrder.getProdOrderCode(), stockEnoughFlag);
            } else {
                log.error("生产订单[{}]库存充足标记更新失败", scProductionOrder.getProdOrderCode());
            }
        } catch (Exception e) {
            log.error("更新生产订单库存充足标记时发生异常：{}", e.getMessage(), e);
        }
    }

    /**
     * 远程调用基础服务生成编码，并健壮地处理返回结果。
     * @param type 编码类型
     * @return 生成的编码字符串
     */
    private String generateCode(Long type) {
        // 调用远程服务（消费模式，确保每次调用都会递增流水号）
        AjaxResult codeResult = basicService.automaticallyNumbersConsume(type);

        // 确保远程调用返回了结果对象
        if (codeResult == null) {
            throw new ServiceException(String.format("远程获取编码调用失败，返回结果为空，类型: %d", type));
        }

        // 根据该接口的特殊设计，编码直接存放在msg字段
        Object msg = codeResult.get(AjaxResult.MSG_TAG);
        Object code=codeResult.get(AjaxResult.CODE_TAG);
        System.out.println("编码是："+code);
        // 确保编码内容不为空
        if (msg == null || msg.toString().isEmpty()) {
            throw new ServiceException(String.format("远程获取编码成功，但返回的编码为空，类型: %d, 返回信息: %s", type, msg));
        }

        // 从AjaxResult中正确取出msg部分作为编码
        return msg.toString();
    }
}